﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Windows.Forms;
using DomainClasses;
using DataLayer;

namespace GPSReceiverHub
{
  public partial class ReceiverHub : Form
  {
    private PostMode ActualPostingMode;
    private string   FolderPath;
    private string   SelectedFile;
    System.Text.ASCIIEncoding Encoder = new System.Text.ASCIIEncoding();

    Context db = new Context();

    public ReceiverHub()
    {
      InitializeComponent();

      comboBoxCOMPorts.Items.AddRange(SerialPort.GetPortNames());
      if (comboBoxCOMPorts.Items.Count > 0) { comboBoxCOMPorts.SelectedIndex = 0; }

      db.Database.Initialize(false);
      foreach (var gprmc in db.GPRMCs)
      {
        db.GPRMCs.Remove(gprmc);
      }
    }

    private void ModeChanged(object sender, EventArgs e)
    {
      if(sender == radioButtonGPS)
      {
        groupBoxConnectToGPS.Enabled  = true;
        groupBoxParseFromFile.Enabled = false;
        groupBoxManualInput.Enabled   = false;
        groupBoxTimedOutput.Enabled   = false;
        groupBoxParseAndLogFile.Enabled = true;
        ActualPostingMode = PostMode.GPS;
      }
      else if(sender == radioButtonFile)
      {
        groupBoxConnectToGPS.Enabled  = false;
        groupBoxParseFromFile.Enabled = true;
        groupBoxManualInput.Enabled   = false;
        groupBoxTimedOutput.Enabled   = true;
        groupBoxParseAndLogFile.Enabled = true;
        ActualPostingMode = PostMode.FromFile;
        DisconnectSerialPort();
      }
      else
      {
        groupBoxConnectToGPS.Enabled  = false;
        groupBoxParseFromFile.Enabled = false;
        groupBoxManualInput.Enabled   = true;
        groupBoxTimedOutput.Enabled   = true;
        groupBoxParseAndLogFile.Enabled = false;
        ActualPostingMode = PostMode.Manual;
        DisconnectSerialPort();
      }
    }

    private void numericUpDownOutputFreq_ValueChanged(object sender, EventArgs e)
    {
      OutputTimer.Interval = (int) ((decimal)1000 / ((NumericUpDown)sender).Value);
    }

    private void OutputTimer_Tick(object sender, EventArgs e)
    {
      if (ActualPostingMode == PostMode.FromFile)
      {
        // TODO: Parse the file and send next data to SQL
      }
      else if(ActualPostingMode == PostMode.Manual)
      {
        // TODO: Parse inputed data and send it to SQL
      }
    }

    private void buttonSelectFolder_Click(object sender, EventArgs e)
    {
      FolderPath = "Select a folder !";

      if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
        FolderPath = folderBrowserDialog.SelectedPath;
      textBoxFolderPath.Text = FolderPath;

      ListAllFilesFromSelectedFolder();
    }

    private void ListAllFilesFromSelectedFolder(string selectedFile = "")
    {
      IDictionary<string, string> FilesAndPath = new Dictionary<string, string>();
      bool empty = false;

      if (FolderPath != "Select a folder !")
      {
        int SubstringIndex = FolderPath.Count() + 1; // +1 for the extra '/'
        string[] allFiles = Directory.GetFiles(FolderPath, "*.txt");

        foreach (string file in allFiles)
          FilesAndPath.Add(file, file.Substring(SubstringIndex));
      }
      else
      {
        FilesAndPath.Add("", "Select a folder first");
        empty = true;
      }

      if(FilesAndPath.Count > 0)
      {
        comboBoxAvailableFiles.DataSource = new BindingSource(FilesAndPath, null);
        comboBoxAvailableFiles.DisplayMember = "Value";
        comboBoxAvailableFiles.ValueMember = "Key";

        if (selectedFile == "")
          comboBoxAvailableFiles.SelectedIndex = 0;
        else if(!empty)
        {
          foreach (var i in comboBoxAvailableFiles.Items)
          {
            if (i.ToString() == selectedFile)
              comboBoxAvailableFiles.SelectedItem = i;
          }
        } 
      }
    }

    private void buttonConnectToGPS_Click(object sender, EventArgs e)
    {
      if (buttonConnectToGPS.Text == "Connect")
        ConnectSerialPortToGPS();
      else
        DisconnectSerialPort();
    }

    private void ConnectSerialPortToGPS()
    {
      serialPortGPS.PortName = comboBoxCOMPorts.SelectedItem.ToString();
      serialPortGPS.BaudRate = 9600;
      serialPortGPS.Parity = Parity.None;
      serialPortGPS.StopBits = StopBits.One;

      try
      {
        serialPortGPS.Open();
      }
      catch (System.IO.IOException error)
      {
        MessageBox.Show("This COM port is probably already in use.\n\nErreur : " + error.ToString(), "COM PORT ERROR", MessageBoxButtons.OK, MessageBoxIcon.Information);
      }

      serialPortGPS.ReadTimeout = 500;
      serialPortGPS.WriteTimeout = 500;

      if (serialPortGPS.IsOpen)
      {
        buttonConnectToGPS.Text = "Disconnect";
        textBoxConnectionStatus.Text = "Connected";
        textBoxConnectionStatus.ForeColor = Color.Green;
      } 
    }

    private void DisconnectSerialPort()
    {
      serialPortGPS.Close();
      buttonConnectToGPS.Text = "Connect";
      textBoxConnectionStatus.Text = "Disconnected";
      textBoxConnectionStatus.ForeColor = Color.White;
    }

    private void serialPortGPS_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
      string receivedLine = serialPortGPS.ReadLine();
      //textBoxLogLines.Text = receivedLine;

      if (checkBoxLogging.Checked && File.Exists(SelectedFile))
      {
        File.AppendAllText(SelectedFile, receivedLine + "\r\n");
      }

      if(receivedLine.Contains("GPRMC"))
      {
        var receivedData = new GPRMC();
        var nextId = 1;
        int HighestId = 0;
        if(db.GPRMCs.Any())
        {
          foreach (var c in db.GPRMCs)
            if (c.GprmcId > HighestId)
              HighestId = c.GprmcId;
        }
        nextId = HighestId + 1;
        receivedData.ParseFromString(receivedLine, nextId);
        db.GPRMCs.Add(receivedData);
        db.SaveChanges();
      }
    }

    private void ParseAndSendFromFile(object sender, EventArgs e)
    {
    }

    private void comboBoxAvailableFiles_SelectedIndexChanged(object sender, EventArgs e)
    {
      SelectedFile = ((ComboBox) sender).SelectedItem.ToString();
      SelectedFile = SelectedFile.TrimStart('[');
      SelectedFile = SelectedFile.Split(',')[0];
      textBoxNewFileName.Text = ((ComboBox) sender).Text;

      File.AppendAllText(SelectedFile, "TEST");
    }

    private void buttonCreateNewFile_Click(object sender, EventArgs e)
    {
      int SubstringIndex = FolderPath.Count() + 1; // +1 for the extra '/'
      bool alreadyExists = false;
      string newFileName = textBoxNewFileName.Text;

      foreach (string s in Directory.GetFiles(FolderPath))
      {
        if (s.Substring(SubstringIndex) == newFileName)
          alreadyExists = true;
      }
      if(alreadyExists)
      {
        MessageBox.Show("A file with the same name already exists in this folder");
      }
      else
      {
        string path = FolderPath + "\\" + newFileName;
        File.Create(path).Dispose();
        ListAllFilesFromSelectedFolder("[" + path + ", " + newFileName + "]");
      }
    }
  }

  enum PostMode
  {
    GPS,
    FromFile,
    Manual
  }
}
